package com.hmall.search.service.impl;

import cn.hutool.json.JSONUtil;
import com.hmall.common.domain.PageDTO;
import com.hmall.common.utils.CollUtils;
import com.hmall.search.domain.po.ItemDoc;
import com.hmall.search.query.ItemPageQuery;
import com.hmall.search.service.SearchService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor
@Slf4j
public class SearchServiceImpl implements SearchService {

    private final RestHighLevelClient client;

    @Override
    public PageDTO<ItemDoc> search(ItemPageQuery query) {
        // 1.准备request
        SearchRequest request = new SearchRequest("items");
        // 2.组织请求参数
        request.source().query(QueryBuilders.matchAllQuery());
        // 分页
        request.source().from((query.getPageNo() - 1) * query.getPageSize()).size(query.getPageSize());
        // 3.发送请求
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("搜索出错了:{}", e.getMessage());
            // 返回一个空的PageDTO，避免返回null
            return new PageDTO<>(0L, query.getPageNo().longValue(), new ArrayList<>());
        }
        // 4.解析响应
        return handleResponse(response, query);
    }

    private PageDTO<ItemDoc> handleResponse(SearchResponse response, ItemPageQuery query) {
        List<ItemDoc> itemDocList = new ArrayList<>();
        SearchHits searchHits = response.getHits();
        // 1.获取总条数
        long total = searchHits.getTotalHits().value;
        System.out.println("共搜索到:" + total + "条数据");
        // 2.遍历结果数组
        for (SearchHit hit : searchHits.getHits()) {
            // 得到_source,也就是原始json文件
            String source = hit.getSourceAsString();
            // 反序列化并打印
            ItemDoc itemDoc = JSONUtil.toBean(source, ItemDoc.class);
            // 获取高亮结果
            Map<String, HighlightField> hfs = hit.getHighlightFields();
            if (CollUtils.isNotEmpty(hfs)) {
                // 获取name字段的高亮结果
                HighlightField hf = hfs.get("name");
                if (hf != null) {
                    // 获取第一个高亮结果，也就是商品名称的高亮值
                    String hfName = hf.getFragments()[0].string();
                    itemDoc.setName(hfName);
                }
            }
            // 添加处理后的itemDoc到列表
            itemDocList.add(itemDoc);
        }
        return new PageDTO<>(total, query.getPageNo().longValue(), itemDocList);
    }
}
